package com.ttt.tank;

import com.ttt.game.Bullet;
import com.ttt.game.Explode;
import com.ttt.game.GameFrame;
import com.ttt.map.MapWall;
import com.ttt.util.*;

import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public abstract class Tank {
    public static final int Dir_Up = 0;
    public static final int Dir_Down = 1;
    public static final int Dir_Left = 2;
    public static final int Dir_Right = 3;
    public static final int Default_Speed = 10;
    public static final int Radius = 20;
    public static final int Default_Hp = 50;
    public int maxHP = Default_Hp;
    //坦克的状态
    public static final int State_Stand = 0;
    public static final int State_Move = 1;
    public static final int State_Die = 2;

    private int x,y;
    //血量
    private int hp = Default_Hp;
    private String name;
    //攻击
    private int atk;
    public static final int Atk_Max = 25;
    public static final int Atk_Min = 15;
    //防御
    private int def;
    //速度
    private int speed = Default_Speed;
    //状态
    private int state = State_Stand;
    private Color color;
    private int dir;
    //射速
    private int rof;
    //子弹
    private boolean isEnemy = false;
    private boolean alive = false;
    private BloodBar bar = new BloodBar();
    private List<Bullet> bullets = new ArrayList();
    //使用容器来保存当前坦克上的所有的爆炸效果
    private List<Explode>explodes = new ArrayList<>();

    public Tank(int x, int y, int dir) {
        this.x = x;
        this.y = y;
        this.dir = dir;
        color = MyUtil.getRandomColor();
        name = MyUtil.getRandomName();
        atk = MyUtil.getRandomNumber(Atk_Min,Atk_Max);
    }
    public Tank(){
        initTank();
    }

    private void initTank(){
        color = MyUtil.getRandomColor();
        name = MyUtil.getRandomName();
        atk = MyUtil.getRandomNumber(Atk_Min,Atk_Max);
    }

    public void draw(Graphics g){
        logic();

        drawImgTank(g);

        drawBullets(g);

        drawName(g);

        bar.draw(g);

    }


    private void drawName(Graphics g){
        g.setColor(color);
        g.setFont(Constant.smallFont);
        g.drawString(name,x - 30,y - 35);
    }

    /**
     * 使用图片的方式绘制坦克
     * @param g
     */
    public abstract void drawImgTank(Graphics g);
//    {
//        if (isEnemy){
//            g.drawImage(enemyImg[dir],x - Radius,y - Radius,null);
//        }else {
//            g.drawImage(tankImg[dir],x - Radius,y - Radius,null);
//        }
//    }

    /**
     * 使用系统方式绘制坦克
     * @param g
     */
    private void drawTank(Graphics g){
        g.setColor(color);
        g.fillOval(x-Radius,y-Radius,Radius<<1,Radius<<1);
        int endX = x;
        int endY = y;
        switch (dir){
            case Dir_Up:
                endY = y -Radius * 2;
                g.drawLine(x-1,y,endX-1,endY);
                g.drawLine(x+1,y,endX+1,endY);
                break;
            case Dir_Down:
                endY = y + Radius * 2;
                g.drawLine(x-1,y,endX-1,endY);
                g.drawLine(x+1,y,endX+1,endY);

                break;
            case Dir_Left:
                endX = x - 2 * Radius;
                g.drawLine(x,y-1,endX,endY-1);
                g.drawLine(x,y+1,endX,endY+1);

                break;
            case Dir_Right:
                endX = x + 2 * Radius;
                g.drawLine(x,y-1,endX,endY-1);
                g.drawLine(x,y+1,endX,endY+1);

                break;
        }
        g.drawLine(x,y,endX,endY);
    }

    //坦克的逻辑处理
    private void logic(){
        switch (state){
            case State_Stand:
                break;
            case State_Move:
                move();
                break;
            case State_Die:
                break;
        }
    }

    private int oldX = -1,oldY = -1;
    //坦克移动的功能
    private void move(){
        oldX = x;
        oldY = y;
        switch (dir){
            case Dir_Up:
                y -= speed;
                if (y < Radius + GameFrame.titleBraH-8){
                    y = Radius + GameFrame.titleBraH-8;
                }
                break;
            case Dir_Down:
                y += speed;
                if (y > Constant.Frame_Height - Radius){
                    y = Constant.Frame_Height - Radius;
                }
                break;
            case Dir_Left:
                x -= speed;
                if (x < Radius){
                    x = Radius;
                }
                break;
            case Dir_Right:
                x += speed;
                if (x > Constant.Frame_Width - Radius){
                    x = Constant.Frame_Width - Radius;
                }
                break;
        }
        //System.out.println(this);
    }

    //上一次开火的时间
    private long fireTime;
    public static final int Fire_Interval = 250;

    //坦克发射炮弹的功能
    public void fire() {
        if (System.currentTimeMillis() - fireTime > Fire_Interval) {
            int bulletX = x;
            int bulletY = y;
            switch (dir) {
                case Dir_Up:
                    bulletY -= (Radius - 10);
                    break;
                case Dir_Down:
                    bulletY += (Radius - 4);
                    break;
                case Dir_Left:
                    bulletX -= (Radius - 8);
                    break;
                case Dir_Right:
                    bulletX += Radius;
                    break;
            }
            //从对象池中获取子弹对象
            Bullet bullet = BulletsPool.get();
            //设置子弹属性
            bullet.setX(bulletX);
            bullet.setY(bulletY);
            bullet.setDir(dir);
            bullet.setAtk(atk);
            bullet.setColor(color);
            bullet.setVisible(true);
            bullets.add(bullet);

            //发射子弹之后，记录本次发射的时间
            fireTime = System.currentTimeMillis();
            //攻击音效导入
            MusicUtil.playAtk();
        }
    }

    /**
     * 将当前坦克的发射的所有子弹绘制出来
     * @param g
     */

    private void drawBullets(Graphics g){
//        for (Bullet bullet : bullets) {
//            bullet.draw(g);
//        }
        for (int i = 0; i < bullets.size(); i++) {
            Bullet bullet = bullets.get(i);
            bullet.draw(g);
        }
        //打印容器中的子弹的个数
//        System.out.println(bullets.size());
        //是遍历所有的子弹，将不可见的子弹移除，并还原回对象池
        for (int i = 0; i < bullets.size(); i++) {
            Bullet bullet = bullets.get(i);
            if (!bullet.isVisible()){
                Bullet remove = bullets.remove(i);
                i--;
                BulletsPool.theReturn(remove);

            }
        }
//        System.out.println("坦克的子弹的数量："+bullets.size());
    }

    //坦克销毁时处理坦克的所有子弹
    public void bulletsReturn(){
//        for (Bullet bullet : bullets) {
//            BulletsPool.theReturn(bullet);
//        }
        for (int i = 0; i < bullets.size(); i++) {
            Bullet bullet = bullets.get(i);
            BulletsPool.theReturn(bullet);
        }
        bullets.clear();
    }

    //坦克和敌人的子弹的碰撞方法
    public void collideBullets(List<Bullet> bullets){
        //遍历所有的子弹，依次和当前的坦克进行碰撞的检测
//        for (Bullet bullet : bullets){
        for (int i = 0; i < bullets.size(); i++) {
            Bullet bullet = bullets.get(i);
            int bulletX = bullet.getX();
            int bulletY = bullet.getY();
            if (MyUtil.isCollide(x,y,Radius,bulletX,bulletY)){
                //子弹消失
                bullet.setVisible(false);
                //坦克收到伤害
                hurt(bullet);
                //添加爆炸效果
                addExplode(x,y + Radius);
            }
        }
        }

//    }

    private void addExplode(int x,int y){
        //添加爆炸效果,以当前被击中的坦克的坐标为参考
        Explode explode = ExplodesPool.get();
        explode.setX(x);
        explode.setY(y);
        explode.setVisible(true);
        explode.setIndex(0);
        explodes.add(explode);
    }

    //坦克受到伤害
    private void hurt(Bullet bullet){
        int atk = bullet.getAtk();
//        System.out.println("atk = "+atk);
        hp -= atk;
        if (hp < 0){
            hp = 0;
            die();

        }
    }

    //坦克死亡
    private void die(){
        if (isEnemy){
            GameFrame.killEnemyCount ++;
            //敌人坦克被消灭 归还对象池
            EnemyTanksPool.theReturn(this);
            //本关是否结束
            if (GameFrame.isCrossLevel()){
                //判断游戏是否通过
                if (GameFrame.isLastLevel()){
                    //通关了
                    GameFrame.setGameState(Constant.State_Win);
                }else {
                    //进入下一关
                    GameFrame.startCrossLevel();
                }
            }
        }else if (alive){
            setState(State_Die);
            //TODO
//            gameover
//            GameFrame.setGameState(Constant.State_Over);

        }else {
            //1.5s后游戏结束
            delaySecondsToOver(1500);
        }

    }

    /**
     * 判断当前的坦克是否死亡
     * @return
     */
    public boolean isDie(){
        return hp <= 0;
    }
    /**
     * 绘制当前坦克的所有的爆炸的效果
     * @param g
     */
    public void drawExplodes(Graphics g){
//        System.out.println(explodes.size());
//        for (Explode explode : explodes) {
//            explode.draw(g);
//           System.out.println(explode);
//        }
        for (int i = 0; i < explodes.size(); i++) {
            Explode explode = explodes.get(i);
            explode.draw(g);
        }
        //将不可见的爆炸效果删除，还回对象池
        for (int i = 0; i < explodes.size(); i++) {
            Explode explode = explodes.get(i);
            if (!explode.isVisible()){
                Explode remove = explodes.remove(i);
                ExplodesPool.theReturn(remove);
                i--;
            }
        }
    }



    //内部类，来表示坦克的血条
    class BloodBar{
        public static final int Bar_Length = 43;
        public static final int Bar_Height = 4;
        public void draw(Graphics g){
            //填充底色
            g.setColor(Color.yellow);
            g.fillRect(x - Radius,y - Radius - Bar_Height * 2,Bar_Length,Bar_Height);
            //红色当前血量
            g.setColor(Color.RED);
            g.fillRect(x - Radius,y - Radius - Bar_Height * 2,hp * Bar_Length / maxHP,Bar_Height);
            //白色的边框
            g.setColor(Color.white);
            g.drawRect(x - Radius,y - Radius - Bar_Height * 2,Bar_Length,Bar_Height);
        }
    }

    //坦克的子弹和地图所有的块的碰撞
    public void bulletsCollideMapWalls(List<MapWall> walls){
//        for (MapWall wall : walls) {
        for (int i = 0; i < walls.size(); i++) {
            MapWall wall = walls.get(i);
            if (wall.isCollideBullet(bullets)){
                //添加爆炸效果
                addExplode(wall.getX() + MapWall.radius,wall.getY() + MapWall.wallW);
                //地图砖块没有击毁处理
                if (wall.getType() == MapWall.Type_Hard)
                    continue;
                //设置地图块销毁
                wall.setVisible(false);
                //归还对象池
                MapWallPool.theReturn(wall);
                //当老巢被击毁后某段时间后切换到游戏菜单界面
                if (wall.isHouse()){
                    //1.5s
                    delaySecondsToOver(1500);
                }
            }
        }
    }

//    }

    /**
     * 延迟 若干毫秒 切换到游戏结束
     * @param millisSecond
     */
    private void delaySecondsToOver(int millisSecond){
        new Thread(){
            public void run(){
                try {
                    Thread.sleep(millisSecond);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                GameFrame.setGameState(Constant.State_Lost);
            }
        }.start();
    }

    /**
     * 一个地图块和当前的坦克碰撞的方法
     * 从wall中提取8个点来判断8个点是否有任何一个点和当前的坦克有了碰撞
     * 点的顺序从左上角开始，顺时针遍历
     */

    public boolean isCollideWall(List<MapWall> walls){
//        for (MapWall wall : walls) {}
        for (int i = 0; i < walls.size(); i++) {
            MapWall wall = walls.get(i);

            //如果块不可见，或者是遮挡块就不进行碰撞的检测
            if (!wall.isVisible() || wall.getType() == MapWall.Type_Cover)
                continue;
            //点-1 左上角点
            int wallX = wall.getX();
            int wallY = wall.getY();
            boolean collide = MyUtil.isCollide(x, y, Radius, wallX, wallY);
            //如果碰上了就直接返回，否则继续判断下一关点
            if (collide){
                return true;
            }
            //点-2 中上点
            wallX += MapWall.radius;
            collide = MyUtil.isCollide(x, y, Radius, wallX, wallY);
            if (collide){
                return true;
            }
            //点-3 右上角点
            wallX += MapWall.radius;
            collide = MyUtil.isCollide(x, y, Radius, wallX, wallY);
            if (collide){
                return true;
            }
            //点-4 右中点
            wallY += MapWall.radius;
            collide = MyUtil.isCollide(x, y, Radius, wallX, wallY);
            if (collide){
                return true;
            }
            //点-5 右下点
            wallY += MapWall.radius;
            collide = MyUtil.isCollide(x, y, Radius, wallX, wallY);
            if (collide){
                return true;
            }
            //点-6 下中点
            wallX -= MapWall.radius;
            collide = MyUtil.isCollide(x, y, Radius, wallX, wallY);
            if (collide){
                return true;
            }
            //点-7 左下点
            wallX -= MapWall.radius;
            collide = MyUtil.isCollide(x, y, Radius, wallX, wallY);
            if (collide){
                return true;
            }
            //点-8 左中点
            wallY -= MapWall.radius;
            collide = MyUtil.isCollide(x, y, Radius, wallX, wallY);
            if (collide){
                return true;
            }
        }
        return false;
    }

    /**
     * 坦克回退的方法
     */
    public void back(){
        //返回上一步所在的位置
        x = oldX;
        y = oldY;

        //按方向判断，会导致穿越
//        switch (dir){
//            case Dir_Up:
//                y += speed;
//                break;
//            case Dir_Down:
//                y -= speed;
//                break;
//            case Dir_Left:
//                x += speed;
//                break;
//            case Dir_Right:
//                x -= speed;
//                break;
//        }
    }


    public Color getColor() {
        return color;
    }

    public void setColor(Color color) {
        this.color = color;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getHp() {
        return hp;
    }

    public void setHp(int hp) {
        this.hp = hp;
    }

    public int getAtk() {
        return atk;
    }

    public void setAtk(int atk) {
        this.atk = atk;
    }

    public int getDef() {
        return def;
    }

    public void setDef(int def) {
        this.def = def;
    }

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }

    public int getDir() {
        return dir;
    }

    public void setDir(int dir) {
        this.dir = dir;
    }

    public int getRof() {
        return rof;
    }

    public void setRof(int rof) {
        this.rof = rof;
    }

    public static int getDir_Up() {
        return Dir_Up;
    }

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
    }

    public boolean isEnemy() {
        return isEnemy;
    }

    public void setEnemy(boolean enemy) {
        isEnemy = enemy;
    }

    public List<Bullet> getBullets() {
        return bullets;
    }

    public void setBullets(List<Bullet> bullets) {
        this.bullets = bullets;
    }

    public int getMaxHP() {
        return maxHP;
    }

    public void setMaxHP(int maxHP) {
        this.maxHP = maxHP;
    }

    public boolean isAlive() {
        return alive;
    }
    public void setAlive(boolean alive) {
        this.alive = alive;
    }

    @Override
    public String toString() {
        return "Tank{" +
                "x=" + x +
                ", y=" + y +
                ", hp=" + hp +
                ", atk=" + atk +
                ", def=" + def +
                ", speed=" + speed +
                ", state=" + state +
                ", dir=" + dir +
                ", rof=" + rof +
                '}';
    }
}
